/*
 * UserListener.java
 *
 * Created on 09 September 2006, 16:12
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package hubsniffer.conn.listener;

import libjdc.dc.io.DCBufferedReader;
import libjdc.dc.io.RemoteFile;
import libjdc.dc.protocol.ClientProtocol;
import libjdc.dc.protocol.Encripter;
import hubsniffer.DCHub;
import libjdc.dc.client.User;
import libjdc.dc.util.TaskFinnishedException;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.text.ParseException;

/**
 *
 * @author root
 */
public class DCUserListener implements Runnable{
    
    private DCHub hub;
    private User myself, other;
    private Socket socket;
    
    // canal de escrita do hub
    private DataOutputStream out;
    private DCBufferedReader in;
 
    private String filename ="files.xml.bz2";
    private int offset;
    
    private boolean isConnected = false;
    
    private RemoteFile remoteFile;
    
    /** Creates a new instance of UserListener */
    public DCUserListener(Socket socket/*,DCHub hub*/,User myself, User other) {
       // setHub(hub);
        setMyself(myself);
        setOther(other);
        setSocket(socket);
        remoteFile = new RemoteFile();
    }
    
    public void run() {
        try {
            out = new DataOutputStream(getSocket().getOutputStream());
            
            in = new DCBufferedReader(new InputStreamReader(getSocket().getInputStream(),"ISO-8859-1"));
            
            
            isConnected = true;
        
            while (isConnected)
                processHubMessage(in.readMessage());
            
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }catch (TaskFinnishedException ex) {
            ex.printStackTrace();
        }
    }
/*
    public DCHub getHub() {
        return hub;
    }

    public void setHub(DCHub hub) {
        this.hub = hub;
    }
*/
    public User getMyself() {
        return myself;
    }

    public void setMyself(User myself) {
        this.myself = myself;
    }

    public User getOther() {
        return other;
    }

    public void setOther(User other) {
        this.other = other;
    }

    private void processHubMessage(String message) throws IOException, TaskFinnishedException {
        System.out.println("<client>" + message);
        try {
            if (message.startsWith(ClientProtocol.DC_S_MESSAGE_LOCK))
                
                handlerLock(message);
            else if (message.startsWith(ClientProtocol.DC_S_MESSAGE_MAXEDOUT))
                handlerMaxedOut(message);
            else if (message.startsWith(ClientProtocol.DC_S_MESSAGE_KEY))
                handlerKey(message);
            else if (message.startsWith(ClientProtocol.DC_S_MESSAGE_GET))
                handlerGet(message);
            else if (message.startsWith(ClientProtocol.DC_S_MESSAGE_FILELENGTH))
                handlerFileLength(message);
        } catch (UnsupportedEncodingException ex) {
            ex.printStackTrace();
        } catch (ParseException ex) {
            ex.printStackTrace();
        }
    }

    private Socket getSocket() {
        return socket;
    }

    private void setSocket(Socket socket) {
        this.socket = socket;
    }

    private void handlerLock(String lock) throws UnsupportedEncodingException, IOException, ParseException {
        
        Object[] obj = ClientProtocol.LOCK_PARSER.parse(lock);
        sendMyNick();
        sendLock();
        sendSupports("MiniSlots XmlBZList ADCGet TTHL TTHF GetZBlock ZLIG ");
        sendDirection("Download",16800);
        sendKey(new Encripter(obj[0].toString()).getKey());
        
    }

    private void handlerQuit(String message) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
    
    private void sendKey(String key) throws UnsupportedEncodingException, IOException{
        Object[] obj ={ key };
        
        sendRaw( ClientProtocol.KEY_PARSER.format(obj) );
    }
    
    public void sendMyNick() throws UnsupportedEncodingException, IOException{
        Object[] obj = { this.myself.getUserInfo().getNick() };
        
        sendRaw( ClientProtocol.MYNICK_PARSER.format( obj ) );
    }
    
    protected void sendRaw(String s) throws UnsupportedEncodingException, IOException{   
        System.out.println(s);
        out.write(s.getBytes("ISO-8859-1"));
        out.flush();
    }

    private void sendValidateNick() throws UnsupportedEncodingException, IOException{
        Object[] obj ={ other.getUserInfo().getNick() };
        
        sendRaw( ClientProtocol.VALIDATE_NICK_PARSER.format(obj) );
    }

    private void handlerMaxedOut(String message) {}

    private void sendLock() throws UnsupportedEncodingException, IOException {
        Object[] obj ={ "EXTENDEDPROTOCOLABCABCABCABCABCABC","DCPLUSPLUS0.668ABCABC" };
        
        sendRaw( ClientProtocol.LOCK_PARSER.format(obj) );
    }

    private void handlerKey(String message) throws UnsupportedEncodingException, IOException {
        sendRaw( "$Get files.xml.bz2$1|" );
        //sendRaw( "$Get Movies/da vinci code/pukka-tdvcb.srt$1|" );
    }

    private void sendDirection(String direction, int number) throws UnsupportedEncodingException, IOException {
        Object[] obj ={ direction,new Integer(number) };
        
        sendRaw( ClientProtocol.DIRECTION_PARSER.format(obj) );
    }

    private void sendSupports(String supports) throws UnsupportedEncodingException, IOException {
        Object[] obj ={ supports };
        
        sendRaw( ClientProtocol.SUPPORTS_PARSER.format(obj) );
    }

    private void handlerGet(String message) throws ParseException, UnsupportedEncodingException, IOException {
        
        Object[] obj = ClientProtocol.GET_PARSER.parse(message);
        
        filename = ((String)obj[0]);
        offset = new Integer((String) obj[1]).intValue();
        remoteFile.setLocalFileName(filename);
        remoteFile.setOffset(offset);
    }

    public void sendGet(String file, int offset) throws UnsupportedEncodingException, IOException {
        Object[] obj ={ file, offset+""};
        
        sendRaw( ClientProtocol.GET_PARSER.format(obj) );
    }

    private void handlerFileLength(String message) throws ParseException, UnsupportedEncodingException, IOException, TaskFinnishedException {
        Object[] obj = ClientProtocol.FILELENGTH_PARSER.parse(message);
        send();
        remoteFile.setLength(Integer.parseInt((obj[0]+"")));
        download(new Integer(obj[0]+"").intValue());
    }

    private void send() throws UnsupportedEncodingException, IOException {
        sendRaw( ClientProtocol.SEND_PARSER );
    }

    private void download(int i) throws IOException, TaskFinnishedException {
        //char[] bytes = in.readBytes(i);
        char[] bytes = in.readBytes(remoteFile);
        BufferedWriter outFile = new BufferedWriter(new FileWriter("/home/dbotelho/lists/"+other.getUserInfo().getNick()+"."+remoteFile.getLocalFileName()));
        outFile.write(bytes,0,bytes.length);
        outFile.close();
        in.close();
        throw new TaskFinnishedException("Terminou de descarregar a Lista: /home/dbotelho/lists/"+other.getUserInfo().getNick()+"."+remoteFile.getLocalFileName());
    }
}
